<template>
  <div style="height: 100vh">
    <div class="header">
      <button class="back-button" @click="back">返回</button>
      <span class="title">工序流程建模 / 装配</span>
      <div class="header-buttons">
        <el-button v-if="showInitialNodeButton" type="primary" link :icon="CirclePlus" @click="openModal">创建初始节点</el-button>
        <el-button type="primary" link :icon="Document" @click="save">保存</el-button>
      </div>
    </div>
    <!-- 弹出窗口 -->
    <el-dialog
      v-model="isModalOpen"
      title="添加工序流程节点"
      width="852px"
      destroy-on-close
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      class="custom-dialog"
      @close="search = ''"
    >
      <el-table
        :data="filterTableData"
        style="width: 100%"
        max-height="400px"
        border
        :header-cell-style="{
          background: '#f5f7fa',
          color: '#606266',
          height: '50px',
          fontWeight: 600
        }"
        :cell-style="{
          height: '45px'
        }"
      >
        <el-table-column prop="processId" label="工序ID" align="center" width="120" />
        <el-table-column prop="processName" label="工序名称" align="center" width="150" />
        <el-table-column prop="description" label="描述" align="center" width="400" show-overflow-tooltip>
          <template #default="scope">
            {{ scope.row.description?.slice(0, 50) }}{{ scope.row.description?.length > 50 ? "..." : "" }}
          </template>
        </el-table-column>
        <el-table-column align="center" width="150">
          <template #header>
            <el-input v-model="search" size="small" placeholder="请输入工序名称" clearable :prefix-icon="Search" />
          </template>
          <template #default="scope">
            <el-button type="primary" link :icon="CirclePlus" @click="handleAddNode(scope.row.processName)"> 添加 </el-button>
          </template>
        </el-table-column>
      </el-table>

      <template #footer>
        <div class="dialog-footer" style="padding-top: 10px">
          <el-button @click="closeModal">取消</el-button>
          <el-button type="primary" @click="closeModal">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <VueFlow
      v-model:nodes="nodes"
      v-model:edges="edges"
      fit-view-on-init
      class="confirm-flow"
      :default-zoom="1.5"
      :min-zoom="0.2"
      :max-zoom="4"
      :default-edge-options="{
        type: 'smoothstep',
        animated: true,
        style: {
          stroke: '#999999',
          strokeWidth: 2
        },
        markerEnd: {
          type: MarkerType.ArrowClosed,
          color: '#999999'
        }
      }"
      :nodes-draggable="false"
    >
      <Background color="#3eaea4" />
      <template #node-default="props">
        <toolBarNode :id="props.id" :data="props.data" @toolbar-action="handleToolbarAction" />
      </template>
    </VueFlow>
  </div>
</template>

<script lang="tsx" setup>
import { onMounted, reactive, ref } from "vue";
import { VueFlow, type Node, type Edge, Position, MarkerType } from "@vue-flow/core";
import { Background } from "@vue-flow/background";
// import { MiniMap } from "@vue-flow/minimap";
// import { Controls } from "@vue-flow/controls";
import { computed } from "vue";
import { useRoute, useRouter } from "vue-router";
import toolBarNode from "@/views/proTable/components/toolBarNode.vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { CirclePlus, Document, Search } from "@element-plus/icons-vue";
import axios from "axios";
import { ref as vueRef } from "vue";

interface Process {
  id?: string;
  processId?: string;
  processName?: string;
  description?: string;
  createTime?: string;
}

const route = useRoute();
const router = useRouter();
const productId = route.params.id as string;
const currentNodeId = ref<string | null>(null);
const nodes = ref<Node[]>([]);
const edges = ref<Edge[]>([]);
const search = ref("");
const showInitialNodeButton = computed(() => nodes.value.length === 0);

// 全部工序列表（后端获取）
const processList = vueRef<Process[]>([]);

const filterTableData = computed(() =>
  processList.value.filter(
    d => !search.value || (d.processName && d.processName.toLowerCase().includes(search.value.toLowerCase()))
  )
);

const back = () => {
  router.push({
    path: "/basicData/productConfig/product"
  });
};

const processes = ref<ProcessDetail[]>([]);

// 定义 ProcessDetail 接口
interface ProcessDetail {
  id: string;
  processId: string;
  processName: string;
  description: string;
  createTime: string;
}

// 获取产品已绑定工序列表（初始化画布）
const getProductProcessList = async () => {
  try {
    const baseUrl = import.meta.env.VITE_BASE_URL;
    const res = await axios.get(`${baseUrl}/api/carbon/getProductProcesses?productId=${productId}`);
    console.log("工序data", res.data);
    if (res.data?.code === 200) {
      processes.value = res.data.data;
      initializeNodesAndEdges();
    } else {
      ElMessage.warning(res.data?.msg || "获取工序列表失败");
    }
  } catch (error) {
    console.error("获取工序列表失败:", error);
    ElMessage.warning("获取工序列表失败");
  }
};

// 获取全部工序（弹窗用）
const fetchAllProcesses = async () => {
  try {
    const baseUrl = import.meta.env.VITE_BASE_URL;
    const res = await axios.get(`${baseUrl}/api/carbon/getAllProcesses`);
    if (res.data?.code === 200) {
      processList.value = res.data.data;
    } else {
      ElMessage.warning(res.data?.msg || "获取全部工序失败");
    }
  } catch (error) {
    console.error("获取全部工序失败", error);
  }
};
// 自动初始化节点和连线
const initializeNodesAndEdges = () => {
  const newNodes: Node[] = processes.value.map((proc, index) => ({
    id: (index + 1).toString(),
    type: "default",
    data: {
      label: proc.processName,
      processId: proc.id,
      toolbarPosition: Position.Right
    },
    position: { x: 250, y: index * 100 }
  }));

  const newEdges: Edge[] = processes.value.slice(0, -1).map((_, index) => ({
    id: `e${index + 1}-${index + 2}`,
    source: (index + 1).toString(),
    target: (index + 2).toString(),
    type: "smoothstep",
    animated: true,
    markerEnd: {
      type: MarkerType.ArrowClosed,
      color: "#999999"
    },
    style: {
      stroke: "#999999",
      strokeWidth: 2
    }
  }));

  nodes.value = newNodes; // 更新节点
  edges.value = newEdges; // 更新连线
};

// 动态添加新节点的函数
const isModalOpen = ref(false); // 控制模态框显示
const selectedNodeType = reactive({
  processName: ""
});

const openModal = () => {
  isModalOpen.value = true;
};

const closeModal = () => {
  isModalOpen.value = false;
  selectedNodeType.processName = ""; // 清空选择
};

const handleToolbarAction = (action: string, nodeId: string) => {
  if (action === "添加") {
    currentNodeId.value = nodeId; // 记录当前操作的节点 ID
    openModal();
  } else if (action === "删除") {
    currentNodeId.value = nodeId;
    ElMessageBox.confirm("是否删除所选项?", "温馨提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
      draggable: true
    }).then(() => {
      deleteNode(nodeId); // 调用删除逻辑
      ElMessage({
        type: "success",
        message: "删除成功!"
      });
    });
  }
};

// 依据当前边关系计算各节点的拓扑顺序，返回按顺序排列的节点 id 列表
const computeOrder = (ns: Node[], es: Edge[]): string[] => {
  const inDegree: Record<string, number> = {};
  ns.forEach(n => {
    inDegree[n.id] = 0;
  });

  es.forEach(e => {
    if (e.target && inDegree[e.target] !== undefined) {
      inDegree[e.target] += 1;
    }
  });

  const queue: string[] = [];
  Object.keys(inDegree).forEach(id => {
    if (inDegree[id] === 0) queue.push(id);
  });

  const ordered: string[] = [];
  while (queue.length) {
    const id = queue.shift() as string;
    ordered.push(id);
    es.forEach(e => {
      if (e.source === id) {
        inDegree[e.target as string] -= 1;
        if (inDegree[e.target as string] === 0) queue.push(e.target as string);
      }
    });
  }
  console.log("计算出的节点顺序", ordered);
  return ordered;
};

const save = async () => {
  try {
    // 1. 计算拓扑顺序
    const orderedNodeIds = computeOrder(nodes.value, edges.value);

    const processesPayload = orderedNodeIds
      .map((nid, idx) => {
        const node = nodes.value.find(n => n.id === nid);
        if (!node) return null;
        return (node.data as any)?.processId ? { processId: (node.data as any).processId, order: idx + 1 } : null;
      })
      .filter(Boolean) as { processId: string; order: number }[];

    if (processesPayload.length === 0) {
      ElMessage.warning("没有可保存的工序");
      return;
    }

    const baseUrl = import.meta.env.VITE_BASE_URL;
    const requestData = {
      productId: Number(productId),
      processes: processesPayload
    };

    const res = await axios.post(`${baseUrl}/api/carbon/saveProductProcess`, requestData);
    if (res.data?.code === 200) {
      ElMessage({ type: "success", message: "保存成功!" });
    } else {
      ElMessage({ type: "error", message: res.data?.msg || "保存失败!" });
    }
  } catch (error) {
    console.error("保存失败:", error);
    ElMessage({ type: "error", message: "保存失败，请稍后重试!" });
  }
};

const deleteNode = (nodeId: string) => {
  // 找到当前操作的节点
  const currentNode = nodes.value.find(node => node.id === nodeId);
  if (!currentNode) {
    console.error("未找到指定的节点");
    return;
  }

  // 找到与当前节点直接相关的连线
  const connectedEdges = edges.value.filter(edge => edge.source === nodeId || edge.target === nodeId);

  // 删除当前节点及其直接相关的连线
  nodes.value = nodes.value.filter(node => node.id !== nodeId);
  edges.value = edges.value.filter(edge => edge.source !== nodeId && edge.target !== nodeId);

  // 判断是否需要重新连线
  const sourceEdge = connectedEdges.find(edge => edge.target === nodeId); // 当前节点的上游边
  const targetEdge = connectedEdges.find(edge => edge.source === nodeId); // 当前节点的下游边

  if (sourceEdge && targetEdge) {
    // 如果有上游和下游节点，重新创建一条边
    edges.value.push({
      id: `e${sourceEdge.source}-${targetEdge.target}`,
      source: sourceEdge.source,
      target: targetEdge.target,
      type: "smoothstep",
      animated: true,
      markerEnd: {
        type: MarkerType.ArrowClosed,
        color: "#999999"
      },
      style: {
        stroke: "#999999",
        strokeWidth: 2
      }
    });
  }

  // 调整所有在当前节点以下的节点位置
  const deletedNodeY = currentNode.position.y; // 被删除节点的 Y 坐标
  nodes.value.forEach(node => {
    if (node.position.y > deletedNodeY) {
      node.position.y -= 100; // 上移 100
    }
  });
};

//新建？还是below
const handleAddNode = (newNodeLabel: string) => {
  // 根据名称找到所选工序对象
  const selectedProcess = processList.value.find(item => item.processName === newNodeLabel);
  if (!selectedProcess) return;

  // 判断是否已存在该工序节点
  const exists = nodes.value.some(node => (node.data as any)?.processId === selectedProcess.id);
  if (exists) {
    ElMessage.warning("该工序已经被选择，无法插入该工序作为节点");
    return;
  }

  if (showInitialNodeButton.value) {
    addInitialNode(newNodeLabel);
  } else {
    // 已有节点，调用 addNodeBelow
    addNodeBelow(currentNodeId.value!, newNodeLabel);
  }
};

const addInitialNode = (nowNodeLabel: string) => {
  // currentNodeId.value = initialNodeId;
  // 创建初始节点
  const initialNode: Node = {
    id: "1",
    type: "default",
    data: {
      label: nowNodeLabel,
      processId: (processList.value.find(item => item.processName === nowNodeLabel) as any)?.id || "",
      toolbarPosition: Position.Right
    },
    position: { x: 250, y: 50 } // 初始节点固定位置
  };
  // 添加初始节点到节点列表
  nodes.value.push(initialNode);
  isModalOpen.value = false;
  selectedNodeType.processName = "";
  ElMessage({
    type: "success",
    message: "添加成功!"
  });
};

const addNodeBelow = (nodeId: string, newNodeLabel: string) => {
  // 找到当前操作的节点
  const currentNode = nodes.value.find(node => node.id === nodeId);
  if (!currentNode) {
    return;
  }

  // 计算新节点的位置（在当前节点的正下方）
  const newNodePosition = {
    x: currentNode.position.x,
    y: currentNode.position.y + 100
  };

  // 找到新节点的 ID
  const newNodeId = (Math.max(...nodes.value.map(node => parseInt(node.id))) + 1).toString();

  // 创建新节点
  const newNode: Node = {
    id: newNodeId,
    type: "default",
    data: {
      label: newNodeLabel,
      processId: (processList.value.find(item => item.processName === newNodeLabel) as any)?.id || "",
      toolbarPosition: Position.Right
    },
    position: newNodePosition
  };

  // 顺移当前节点以下的节点
  nodes.value.forEach(node => {
    if (node.position.y > currentNode.position.y) {
      node.position.y += 100; // 每个节点向下移动 100
    }
  });

  // 查找当前节点的直接下游节点
  const downstreamEdges = edges.value.filter(edge => edge.source === nodeId);
  const downstreamTargets = downstreamEdges.map(edge => edge.target);

  // 删除当前节点的下游连线
  edges.value = edges.value.filter(edge => edge.source !== nodeId);

  // 添加新节点
  nodes.value.push(newNode);

  // 创建新连线，从当前节点到新节点
  edges.value.push({
    id: `e${currentNode.id}-${newNodeId}`,
    source: currentNode.id,
    target: newNodeId,
    type: "smoothstep",
    animated: true,
    markerEnd: {
      type: MarkerType.ArrowClosed,
      color: "#999999"
    },
    style: {
      stroke: "#999999",
      strokeWidth: 2
    }
  });

  // 将原来的下游节点与新节点重新连接
  downstreamTargets.forEach(targetId => {
    edges.value.push({
      id: `e${newNodeId}-${targetId}`,
      source: newNodeId,
      target: targetId,
      type: "smoothstep",
      animated: true,
      markerEnd: {
        type: MarkerType.ArrowClosed,
        color: "#999999"
      },
      style: {
        stroke: "#999999",
        strokeWidth: 2
      }
    });
  });

  // 关闭模态框并清空选择
  isModalOpen.value = false;
  selectedNodeType.processName = "";
  ElMessage({
    type: "success",
    message: "添加成功!"
  });
};

onMounted(() => {
  getProductProcessList();
  fetchAllProcesses();
});
</script>

<style>
.header {
  display: flex;
  align-items: center;
  justify-content: space-between; /* 左右分布 */
  padding: 10px 20px;
  background-color: #ffffff;
  border-bottom: 1px solid #dddddd;
  border-radius: 8px;
}
.header-buttons {
  display: flex;
  gap: 10px; /* 按钮之间的间距 */
  margin-left: auto; /* 将按钮推到最右侧 */
}
.back-button {
  padding: 8px 12px;
  margin-right: 20px;
  font-size: 14px;
  color: white;
  cursor: pointer;
  background-color: #009688;
  border: none;
  border-radius: 4px;
  transition: background-color 0.2s ease;
}
.back-button:hover {
  background-color: #007d6a;
}
.title {
  font-size: 18px;
  font-weight: bold;
  color: #333333;
}
.modal-content {
  z-index: 10000;
  width: 300px;
  padding: 20px;
  text-align: center;
  background: white;
  border-radius: 5px;
}
select {
  width: 100%;
  padding: 8px;
  margin: 10px 0;
  border: 1px solid #cccccc;
  border-radius: 4px;
}
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: 1000;
  width: 400px;
  max-width: 90%;
  height: auto;
  padding: 20px;
  background-color: white;
  border-radius: 8px;
  transform: translate(-50%, -50%);
}
.vue-flow__node-toolbar {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  padding: 8px;
  background-color: #2d3748;
  border-radius: 8px;
  box-shadow: 0 0 10px rgb(0 0 0 / 50%);
}
.vue-flow__node-toolbar button {
  padding: 0.5rem 1rem;
  color: white;
  cursor: pointer;
  background: #4a5568;
  border: none;
  border-radius: 8px;
}
.vue-flow__node-toolbar button.selected {
  background: #009688;
}
.vue-flow__node-toolbar button:hover {
  background: #009688;
}
.vue-flow__node-default {
  padding: 20px;
  background: #e6f5f3;
  border: 1px solid var(--el-color-primary);
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
  transition: all 0.3s ease;
}
.node-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--el-color-primary);
}
</style>
